package g2.routemaster.gui.contents;

import g2.routemaster.gui.ApplicationStart;
import g2.routemaster.gui.BoardSingleton;
import g2.routemaster.gui.GManager;
import g2.routemaster.gui.actions.PlayCardAction;
import g2.routemaster.gui.actions.ScoringAction;
import g2.routemaster.gui.dialogs.DrawCardDialog;
import g2.routemaster.gui.general.ECityCard;
import g2.routemaster.gui.general.ImageRegistry;
import g2.routemaster.model.Board;
import g2.routemaster.model.BonusPile;
import g2.routemaster.model.City;
import g2.routemaster.model.CityCard;
import g2.routemaster.model.GameManager;
import g2.routemaster.model.OpenStack;
import g2.routemaster.model.Player;
import g2.routemaster.model.TurnManager;

import java.util.Iterator;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;

public class BoardCardsGroup extends Composite {
   private Image imageBlind;
   private CLabel lBlind;
   private Composite openCardComposite;
   private Button bPlay;
   private Button bDraw;
   private Button bScore;
   private Button bEndTurn;


   public BoardCardsGroup(Composite parent, int style) {
      super(parent, style);

      imageBlind = new Image(parent.getDisplay(), getClass().getResourceAsStream("/pic/blindstack.png"));
   }

   public void create(){
      Composite group = new Composite(this, SWT.NONE);
      GridLayout layout = new GridLayout();
      layout.numColumns = 2;
      layout.horizontalSpacing = 0;
      layout.verticalSpacing = 0;
      layout.marginWidth = 0;
      group.setLayout(layout);
      group.setLayoutData(new GridData(GridData.FILL_BOTH));

      openCardComposite = new Composite(group, SWT.NONE);
      layout = new GridLayout();
      layout.numColumns = 2;
      layout.horizontalSpacing = 0;
      layout.verticalSpacing = 0;
      layout.marginWidth = 0;
      openCardComposite.setLayout(layout);
      openCardComposite.setLayoutData(new GridData(GridData.FILL_BOTH));

      Composite blindCardComposite = new Composite(group, SWT.NONE);
      blindCardComposite.setLayout(new GridLayout());
      blindCardComposite.setLayoutData(new GridData(GridData.FILL_BOTH));

      GridData gd = new GridData(GridData.FILL_HORIZONTAL);
      gd.horizontalSpan = 2;

      bDraw = new Button(group, SWT.PUSH);
      bDraw.setText("Draw Card");
      bDraw.setLayoutData(gd);

      bPlay = new Button(group, SWT.PUSH);
      bPlay.setText("Play Card");
      bPlay.setLayoutData(gd);

      bScore = new Button(group, SWT.PUSH);
      bScore.setText("Score");
      bScore.setLayoutData(gd);

      bEndTurn = new Button(group, SWT.PUSH);
      bEndTurn.setText("End Turn");
      bEndTurn.setLayoutData(gd);

      Cursor handCursor = new Cursor(getDisplay(), SWT.CURSOR_HAND);

      lBlind = new CLabel(blindCardComposite, SWT.PUSH);
      lBlind.setImage(imageBlind);
      lBlind.setCursor(handCursor);
      lBlind.addListener(SWT.MouseDown, new Listener(){
         public void handleEvent(Event e){
            if(lBlind.getBackground().equals(getSelectedColor())){
               unselectPlace(lBlind);
            } else {
               for(Control place : openCardComposite.getChildren()){
                  unselectPlace((CLabel)place);
               }
               selectPlace(lBlind);
            }
         }
      });

      bDraw.addListener(SWT.Selection, new Listener(){
         public void handleEvent(Event e){
            GameManager gm = GManager.instance().getGameManager();
            Board board = gm.getBoard();
            Player player = gm.getTurnManager().getPlayer();
            CLabel selectedPlace = getSelectedPlace();

            if(player != null && selectedPlace != null){
               if(selectedPlace.equals(lBlind)){
                  City city = board.getBlindStack().getFirstOfCityCard().getCity();
                  DrawCardDialog dial = new DrawCardDialog(getShell());
                  dial.setMessage("You draw '" +city.getName()+ "' from BlindStack!");
                  dial.setImage(ImageRegistry.getCity(ECityCard.byNom(city.getName())));
                  dial.open();
                  board.drawCardFromBlindStack(player);
               } else {
                  board.drawCardFromOpenStack(
                        player, 
                        (CityCard)selectedPlace.getData());
                  refreshCityCards();
               }
               unselectPlace(selectedPlace);

               // update player data
               BoardSingleton.instance().updatePlayerData();

               // update buttons
               updateData();
            } else {
               MessageDialog.openError(
                     getShell(),
                     "Error",
               "Please select a card first!");
            }
         }
      });

      bPlay.addListener(SWT.Selection, new Listener(){
         public void handleEvent(Event e){
            new PlayCardAction(GManager.instance().getWindow()).run();
         }
      });

      bScore.addListener(SWT.Selection, new Listener(){
         public void handleEvent(Event e){
            new ScoringAction(GManager.instance().getWindow()).run();
         }
      });

      bEndTurn.addListener(SWT.Selection, new Listener(){
         public void handleEvent(Event e){
            GameManager gm = GManager.instance().getGameManager();
            System.out.println("");
            if(isFinalRound(gm)){ 
               Player firstPlayer = gm.getFirstPlayer();
               Player nextPlayer = gm.getNextPlayer(gm.getTurnManager().getPlayer());
               if(firstPlayer.equals(nextPlayer)){
                  Player winner = gm.getWinner();
                  String name = winner.getName();
                  MessageDialog.openInformation(
                        getShell(), 
                        "Game Over", 
                        "Congratulations! The Winner is '"+name+"'.");
                  Player p1 = gm.getFirstPlayer();
                  Player p2 = gm.getNextPlayer(p1);
                  GManager.instance().restart();
                  GameManager newGM = GManager.instance().getGameManager();
                  newGM.insertPlayer(p1.getName(), p1.getBirth(), p1.getColor().getName());
                  newGM.insertPlayer(p2.getName(), p2.getBirth(), p2.getColor().getName());
                  ((ApplicationStart)GManager.instance().getWindow()).createWaitingGroup();
                  ((ApplicationStart)GManager.instance().getWindow()).updateWaitingList();
                  return;
               } else {
                  gm.nextTurn();
                  BoardSingleton.instance().updateAll();
               }
            } else {
               gm.nextTurn();
               BoardSingleton.instance().updateAll();
            }
         }
      });

      for(int i=0; i<6; i++){
         final CLabel cardPlace = new CLabel(openCardComposite, SWT.PUSH);
         cardPlace.setImage(ImageRegistry.getCity(ECityCard.UNKNOWN));
         cardPlace.setCursor(handCursor);
         cardPlace.addListener(SWT.MouseDown, new Listener(){
            public void handleEvent(Event e){
               if(cardPlace.getBackground().equals(getSelectedColor())){
                  unselectPlace(cardPlace);
               } else {
                  for(Control place : openCardComposite.getChildren()){
                     unselectPlace((CLabel)place);
                     unselectPlace(lBlind);
                  }
                  selectPlace(cardPlace);
               }
            }
         });
      }

      refreshCityCards();
   }
   
   // TODO: implement it correctly in Fujaba
   boolean isFinalRound(GameManager gm){
      Iterator iterPile = gm.getBoard().iteratorOfBonusPile();
      while(iterPile.hasNext()){
         BonusPile next = (BonusPile)iterPile.next();
         if(next.getName().equals("Spielende")){
            int bonusTiles = next.sizeOfBonusTiles();
            return bonusTiles == 0;
         }
      }
      return false;
   }

   Color getSelectedColor(){
      return getDisplay().getSystemColor(SWT.COLOR_YELLOW);
   }

   Color getUnselectedColor(){
      return getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
   }

   void refreshCityCards(){
      GameManager gm = GManager.instance().getGameManager();
      Board board = gm.getBoard();
      OpenStack openStack = board.getOpenStack();
      Iterator iter = openStack.iteratorOfCityCard();
      Control[] cardPlaces = openCardComposite.getChildren();
      int i = 0;
      while(iter.hasNext()){
         CityCard card = (CityCard)iter.next();
         CLabel cardPlace = (CLabel)cardPlaces[i++];
         cardPlace.setToolTipText(card.getCity().getName());
         cardPlace.setData(card);
         cardPlace.setImage(ImageRegistry.getCity(ECityCard.byNom(card.getCity().getName())));
      }
      
      // update blind stack
      cleanBlindStack();
      GC gc = new GC(imageBlind);
      gc.setFont(getBlindStackFont());
      drawBlindStackNumber(gc, gm.getBoard().getBlindStack().sizeOfCityCard());
      gc.dispose();
      lBlind.redraw();
   }

   void unselectPlace(CLabel label){
      label.setBackground(getUnselectedColor());
   }

   void selectPlace(CLabel label){
      label.setBackground(getSelectedColor());
   }

   CLabel getSelectedPlace(){
      if(lBlind.getBackground().equals(getSelectedColor())){
         return lBlind;
      } else {
         for(Control child : openCardComposite.getChildren()){
            CLabel cardPlace = (CLabel)child;
            if(cardPlace.getBackground().equals(getSelectedColor())){
               return cardPlace;
            }
         }
      }
      return null;
   }

   public void updateData(){
      GameManager gm = GManager.instance().getGameManager();
      TurnManager tm = gm.getTurnManager();
      bDraw.setEnabled(tm.canDrawCard());
      bPlay.setEnabled(tm.canPlayCard());
      bScore.setEnabled(tm.canScore());
      bEndTurn.setEnabled(tm.canEndTurn());
      
      // update city cards
      refreshCityCards();
   }
   
   void drawBlindStackNumber(GC gc, int value){
      // draw value
      gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
      gc.drawString("-" + String.valueOf(value) + "-", 12, 25, true);
   }
   
   Font getBlindStackFont() {
      Font font = Display.getCurrent().getSystemFont();
      FontData fontData = font.getFontData()[0];
      fontData.setHeight(7);
      return new Font(Display.getCurrent(), fontData);
   }
   
   void cleanBlindStack(){
      imageBlind = new Image(Display.getCurrent(), getClass()
            .getResourceAsStream("/pic/blindstack.png"));
      lBlind.setImage(imageBlind);
      lBlind.redraw();
   }
   
}
